package com.tuanzi.loan.business.service.receipt.product.impl;

import java.util.List;
import java.util.Objects;

import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.retry.RetryException;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.tuanzi.loan.business.entity.receipt.product.ReceiptProductCondition;
import com.tuanzi.loan.business.entity.receipt.product.ReceiptProductInfo;
import com.tuanzi.loan.business.repository.receipt.product.ReceiptProductConditionRepository;
import com.tuanzi.loan.business.repository.receipt.product.ReceiptProductInfoRepository;
import com.tuanzi.loan.business.service.receipt.product.ReceiptProductInfoService;
import com.tuanzi.loan.core.aspect.Debug;
import com.tuanzi.loan.core.exception.SystemException;
import com.tuanzi.loan.core.repository.JPAAuditRepository;
import com.tuanzi.loan.core.service.BaseAuditServiceImpl;
import com.tuanzi.loan.core.vo.PageSearcher;
import com.tuanzi.loan.vo.request.receipt.product.ReceiptProductInfoSearchRequest;
import com.tuanzi.loan.vo.response.receipt.product.ReceiptProductInfoSearchResponse;
import com.tuanzi.server.loan_base.constant.LoanReceiptProductStatus;
import com.tuanzi.server.loan_base.constant.LoanRedisKey;

import lombok.extern.slf4j.Slf4j;

/**
 * @author Ray 2017/09/21
 */
@Debug
@Slf4j
@Service
@Transactional
@Retryable(value = { RetryException.class })
public class ReceiptProductInfoServiceImpl extends BaseAuditServiceImpl<ReceiptProductInfo, Long> implements ReceiptProductInfoService {

	@Autowired
	private ReceiptProductInfoRepository receiptProductInfoRepository;
	@Autowired
	private ReceiptProductConditionRepository receiptProductConditionRepository;
	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Override
	protected JPAAuditRepository<ReceiptProductInfo, Long> getRepository() {
		return receiptProductInfoRepository;
	}

	@Override
	public Page<ReceiptProductInfoSearchResponse> list(PageSearcher<ReceiptProductInfoSearchRequest> pageSearcher) {
		return receiptProductInfoRepository.list(pageSearcher.getSearchCondition(), pageSearcher.getPageable());
	}

	@Override
	public ReceiptProductInfo findEarliestProductInfoByUserIdAndStatusIn(String userId, List<LoanReceiptProductStatus> statusIn) {
		List<ReceiptProductInfo> productInfoList = receiptProductInfoRepository.findProductInfoByUserIdAndStatusIn(userId, statusIn);
		if (productInfoList.size() > 0) {
			return productInfoList.get(0);
		}
		return null;
	}

	@Override
	public List<ReceiptProductInfo> findAllProductIdAndName() {
		return receiptProductInfoRepository.findAllProductIdAndName();
	}

	@Override
	public void sortUp(Long productId) {

		ReceiptProductInfo upReceiptProductInfo = receiptProductInfoRepository.findOne(productId);
		ReceiptProductInfo downReceiptProductInfo = receiptProductInfoRepository.findBySortAndStatusIn(upReceiptProductInfo.getSort() - 1,
				Lists.newArrayList(LoanReceiptProductStatus.ONLINE, LoanReceiptProductStatus.OFFLINE));

		if (downReceiptProductInfo == null) {
			throw new SystemException("没有可排序产品");
		}
		downReceiptProductInfo.setSort(downReceiptProductInfo.getSort() + 1);
		upReceiptProductInfo.setSort(upReceiptProductInfo.getSort() - 1);

		receiptProductInfoRepository.save(upReceiptProductInfo);
		receiptProductInfoRepository.save(downReceiptProductInfo);
		stringRedisTemplate.delete(LoanRedisKey.LOAN_RECEIPT_PRODUCT_LIST);
	}

	@Override
	public void sortDown(Long productId) {
		ReceiptProductInfo downReceiptProductInfo = receiptProductInfoRepository.findOne(productId);
		ReceiptProductInfo upReceiptProductInfo = receiptProductInfoRepository.findBySortAndStatusIn(downReceiptProductInfo.getSort() + 1,
				Lists.newArrayList(LoanReceiptProductStatus.ONLINE, LoanReceiptProductStatus.OFFLINE));

		if (upReceiptProductInfo == null) {
			throw new SystemException("没有可排序产品");
		}

		downReceiptProductInfo.setSort(downReceiptProductInfo.getSort() + 1);
		upReceiptProductInfo.setSort(upReceiptProductInfo.getSort() - 1);
		receiptProductInfoRepository.save(upReceiptProductInfo);
		receiptProductInfoRepository.save(downReceiptProductInfo);
		stringRedisTemplate.delete(LoanRedisKey.LOAN_RECEIPT_PRODUCT_LIST);
	}

	@Override
	public void updateProductInfoAndConditionByStatus(ReceiptProductInfo receiptProductInfo, ReceiptProductCondition receiptProductCondition, LoanReceiptProductStatus status) {
		if (Objects.nonNull(receiptProductInfo) && Objects.nonNull(receiptProductCondition)) {
			receiptProductInfo.setStatus(status);
			receiptProductCondition.setStatus(status);
			if (null == receiptProductCondition.getProductId()) {
				receiptProductCondition.setProductId(receiptProductInfo.getId());
			}
			receiptProductInfoRepository.save(receiptProductInfo);
			receiptProductConditionRepository.save(receiptProductCondition);
			onlineOrOfflineOneKeyProduct(receiptProductInfo);
		}
	}

	@Override
	public void onlineOneKey(Long productId) {
		ReceiptProductInfo receiptProductInfo = receiptProductInfoRepository.findOne(productId);
		receiptProductInfo.setJoinOneKey(true);
		receiptProductInfoRepository.save(receiptProductInfo);
		onlineOrOfflineOneKeyProduct(receiptProductInfo);
	}

	@Override
	public void offlineOneKey(Long productId) {
		ReceiptProductInfo receiptProductInfo = receiptProductInfoRepository.findOne(productId);
		receiptProductInfo.setJoinOneKey(false);
		receiptProductInfoRepository.save(receiptProductInfo);
		onlineOrOfflineOneKeyProduct(receiptProductInfo);
	}

	private void onlineOrOfflineOneKeyProduct(ReceiptProductInfo receiptProductInfo) {
		if (receiptProductInfo.getStatus() == LoanReceiptProductStatus.ONLINE && receiptProductInfo.getJoinOneKey()) {
			stringRedisTemplate.boundSetOps(LoanRedisKey.LOAN_RECEIPT_ONE_KEY_PRODUCTS).add(receiptProductInfo.getId().toString());
			stringRedisTemplate.boundValueOps(LoanRedisKey.LOAN_RECEIPT_ONE_KEY_ORDER_LIMIT + receiptProductInfo.getId())
					.set(String.valueOf(Math.round(receiptProductInfo.getLimitOrderOfDay() * 0.6F)));
		} else {
			stringRedisTemplate.boundSetOps(LoanRedisKey.LOAN_RECEIPT_ONE_KEY_PRODUCTS).remove(receiptProductInfo.getId().toString());
			stringRedisTemplate.delete(LoanRedisKey.LOAN_RECEIPT_ONE_KEY_ORDER_LIMIT + receiptProductInfo.getId());
		}
	}

}
